// Copyright (c) 2010 Shardul Deo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package com.googlecode.protobuf.socketrpc;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.DefaultChannelPromise;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.protobuf.BlockingRpcChannel;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcChannel;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;
import com.google.protobuf.Descriptors.MethodDescriptor;
import com.googlecode.protobuf.socketrpc.SocketRpcProtos.ErrorReason;
import com.googlecode.protobuf.socketrpc.SocketRpcProtos.Response;

/**
 * {@link RpcChannel} implementation that uses a {@link RpcConnectionFactory} to
 * perform blocking and non-blocking rpcs.
 * 
 * @author Shardul Deo
 */
class RpcChannelImpl implements RpcChannel, BlockingRpcChannel {

	private final static Logger LOG = Logger.getLogger(RpcChannelImpl.class
			.getName());

	private final Channel channel;
	private final Executor executor;

	RpcChannelImpl(Channel channel, Executor executor) {
		this.channel = channel;
		this.executor = executor;
	}

	/* (non-Javadoc)
	 * @see com.google.protobuf.RpcChannel#callMethod(com.google.protobuf.Descriptors.MethodDescriptor, com.google.protobuf.RpcController, com.google.protobuf.Message, com.google.protobuf.Message, com.google.protobuf.RpcCallback)
	 * 通用的函数调用。异步方式返回，因为我用了netty 是异步IO 所以暂时没有返回数据 
	 */
	@Override
	public void callMethod(MethodDescriptor method, RpcController controller,
			Message request, final Message responsePrototype,
			final RpcCallback<Message> done) {
		// Must pass in a SocketRpcController
		final SocketRpcController socketController = (SocketRpcController) controller;

		try {
			sendRpcRequest(method, socketController, request);
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/* (non-Javadoc)
	 * @see com.google.protobuf.BlockingRpcChannel#callBlockingMethod(com.google.protobuf.Descriptors.MethodDescriptor, com.google.protobuf.RpcController, com.google.protobuf.Message, com.google.protobuf.Message)
	 * 通用的函数调用。同步方式返回，因为我用了netty 是异步IO 所以暂时没有返回数据 
	 */
	@Override
	public Message callBlockingMethod(MethodDescriptor method,
			RpcController controller, Message request, Message responsePrototype)
			throws ServiceException {
		// Must pass in a SocketRpcController
		SocketRpcController socketController = (SocketRpcController) controller;
		// final Connection connection = createConnection(socketController);

		sendRpcRequest(method, socketController, request);
		
		return null;
	}

	/**
	 * @param method
	 * @param socketController
	 * @param request
	 * @throws ServiceException
	 * 构建远程调用的数据协议，并且发送
	 */
	private void sendRpcRequest(MethodDescriptor method,
			SocketRpcController socketController, Message request)
			throws ServiceException {
		//
		// Create RPC request protobuf
		SocketRpcProtos.Request rpcRequest = SocketRpcProtos.Request
				.newBuilder().setRequestProto(request.toByteString())
				.setServiceName(method.getService().getFullName())
				.setMethodName(method.getName()).build();

		this.channel.writeAndFlush(SocketRpcProtos.ProtocolMessage.newBuilder().setRequest(rpcRequest).build());
		
		 
	}

}